﻿using System;
using System.Collections.Generic;
using System.Text;

using DigitalQuran.Collection;
using DigitalQuran.Extensions;

namespace DigitalQuran
{
    /// <summary>
    /// Represent selection made by user
    /// </summary>
    public class Selection
    {
        /// <summary>
        /// Creates new instance of Selection
        /// </summary>
        /// <param name="scope">Selction scope</param>
        /// <param name="indexes">list of selected item indexes</param>
        public Selection(QuranObjectType scope, List<int> indexes)
        {
            Scope = scope;
            Indexes = indexes;
        }

        /// <summary>
        /// Gets or sets the Scope of Selection
        /// </summary>
        public QuranObjectType Scope { get; set; }

        /// <summary>
        /// Gets the Indexes for selected Scope
        /// </summary>
        public List<int> Indexes { get; private set; }

        VerseCollection _Verses = null;
        /// <summary>
        /// Gets Collection of Verse Selected by User
        /// </summary>
        public VerseCollection Verses {
            get {
                if (_Verses == null) {
                    var list = new List<int>();
                    VerseSpan vSpan;

                    switch (Scope) {
                        case QuranObjectType.Book:
                            _Verses = Book.Instance.Verses;
                            break;
                        case QuranObjectType.Bowing:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Bowings[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Chapter:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Chapters[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Group:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Groups[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Page:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Pages[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Part:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Parts[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Quarter:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Quarters[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Station:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Stations[index];
                                list.AddRange(vSpan.FirstVerse.GlobalNumber - 1, vSpan.LastVerse.GlobalNumber);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Verse:
                            _Verses = new VerseCollectionEx(Indexes);
                            break;
                        case QuranObjectType.Word:
                            foreach (var index in Indexes) {
                                list.Add(Book.Instance.Words[index].Verse.GlobalNumber - 1);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;
                        case QuranObjectType.Letter:
                            foreach (var index in Indexes) {
                                list.Add(Book.Instance.Words.GetLetter(index).Word.Verse.GlobalNumber - 1);
                            }
                            _Verses = new VerseCollectionEx(list);
                            break;            
                    }
                }
                
                return _Verses;
            }
        }

        ChapterCollection _Chapter = null;
        /// <summary>
        /// Gets Collection the Chapter Selected by User
        /// </summary>
        public ChapterCollection Chapters {
            get {
                if (_Chapter == null) {

                    VerseSpan vSpan;
                    var list = new List<int>();

                    switch (Scope) {
                        case QuranObjectType.Book:
                            _Chapter = Book.Instance.Chapters;
                            break;
                        case QuranObjectType.Bowing:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Bowings[index];
                                list.AddRange(vSpan.FirstVerse.Chapter.GlobalNumber - 1, vSpan.LastVerse.Chapter.GlobalNumber);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Chapter:
                            _Chapter = new ChapterCollectionEx(Indexes);
                            break;
                        case QuranObjectType.Group:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Groups[index];
                                list.AddRange(vSpan.FirstVerse.Chapter.GlobalNumber - 1, vSpan.LastVerse.Chapter.GlobalNumber);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Page:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Pages[index];
                                list.AddRange(vSpan.FirstVerse.Chapter.GlobalNumber - 1, vSpan.LastVerse.Chapter.GlobalNumber);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Part:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Parts[index];
                                list.AddRange(vSpan.FirstVerse.Chapter.GlobalNumber - 1, vSpan.LastVerse.Chapter.GlobalNumber);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Quarter:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Quarters[index];
                                list.AddRange(vSpan.FirstVerse.Chapter.GlobalNumber - 1, vSpan.LastVerse.Chapter.GlobalNumber);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Station:
                            foreach (var index in Indexes) {
                                vSpan = Book.Instance.Stations[index];
                                list.AddRange(vSpan.FirstVerse.Chapter.GlobalNumber - 1, vSpan.LastVerse.Chapter.GlobalNumber);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Verse:
                            foreach (var index in Indexes) {
                                list.Add(Book.Instance.Verses[index].Chapter.GlobalNumber - 1);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Word:
                            foreach (var index in Indexes) {
                                list.Add(Book.Instance.Words[index].Verse.Chapter.GlobalNumber - 1);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                        case QuranObjectType.Letter:
                            foreach (var index in Indexes) {
                                list.Add(Book.Instance.Words.GetLetter(index).Word.Verse.Chapter.GlobalNumber - 1);
                            }
                            _Chapter = new ChapterCollectionEx(list);
                            break;
                    }
                }
                
                return _Chapter;
            }
        }

        /// <summary>
        /// Gets the Qur'an text in this selection for specific text mode
        /// </summary>
        /// <param name="textMode">name of text mode whose text to get</param>
        /// <returns>Return Qur'an text in this selection</returns>
        public string ToString(string textMode)
        {
            if (this.Indexes != null)
            {
                StringBuilder str = new StringBuilder();
                var book = Book.Instance;                

                switch (Scope)
                {
                    case QuranObjectType.Book:
                        return book.ToString(textMode);                        
                    case QuranObjectType.Bowing:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < BowingCollection.TotalBowings)
                                str.Append(book.Bowings[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Chapter:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < ChapterCollection.TotalChapters)
                                str.Append(book.Chapters[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Group:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < GroupCollection.TotalGroups)
                                str.Append(book.Groups[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Letter:
                        int count = book.GetCount(QuranObjectType.Letter);
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < count)
                                str.Append(book.GetObject(QuranObjectType.Letter, index).ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Page:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < PageCollection.TotalPages)
                                str.Append(book.Pages[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Part:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < PartCollection.TotalParts)
                                str.Append(book.Parts[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Quarter:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < QuarterCollection.TotalQuarters)
                                str.Append(book.Quarters[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Station:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < StationCollection.TotalStations)
                                str.Append(book.Stations[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Verse:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < VerseCollection.TotalVerses)
                                str.Append(book.Verses[index].ToString(textMode));
                        }
                        break;
                    case QuranObjectType.Word:
                        foreach (var index in Indexes)
                        {
                            if (index >= 0 && index < WordCollection.TotalWords)
                                str.Append(book.Words[index].ToString(textMode));
                        }
                        break;
                }
                                
                return str.ToString();
            }

            return String.Empty;
        }
    }
}